#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
数据可视化模块
负责生成彩票数据的统计图表和分析报告
"""

import plotly.graph_objects as go
import plotly.express as px
from plotly.subplots import make_subplots
import pandas as pd
import numpy as np
from collections import Counter
import json
from datetime import datetime, timedelta
from .database import DatabaseManager

class DataVisualizer:
    def __init__(self):
        self.db_manager = DatabaseManager()
    
    def generate_statistics(self, lottery_type='ssq'):
        """生成统计数据"""
        historical_data = self.db_manager.get_all_data(lottery_type)
        
        if not historical_data:
            return {'error': '没有历史数据'}
        
        if lottery_type == 'ssq':
            return self.generate_ssq_statistics(historical_data)
        elif lottery_type == 'dlt':
            return self.generate_dlt_statistics(historical_data)
        else:
            return {'error': f'不支持的彩票类型: {lottery_type}'}
    
    def generate_ssq_statistics(self, historical_data):
        """生成双色球统计数据"""
        stats = {
            'total_periods': len(historical_data),
            'date_range': {
                'start': historical_data[-1]['draw_date'] if historical_data else None,
                'end': historical_data[0]['draw_date'] if historical_data else None
            }
        }
        
        # 红球统计
        red_stats = self.analyze_red_balls(historical_data)
        stats['red_ball_stats'] = red_stats
        
        # 蓝球统计
        blue_stats = self.analyze_blue_balls(historical_data)
        stats['blue_ball_stats'] = blue_stats
        
        # 号码模式分析
        pattern_stats = self.analyze_number_patterns(historical_data)
        stats['pattern_stats'] = pattern_stats
        
        # 生成图表数据
        charts = self.generate_ssq_charts(historical_data)
        stats['charts'] = charts
        
        return stats
    
    def analyze_red_balls(self, historical_data):
        """分析红球统计"""
        red_counter = Counter()
        all_red_balls = []
        
        for record in historical_data:
            for red in record['red_balls']:
                red_counter[red] += 1
                all_red_balls.append(red)
        
        # 频率统计
        total_draws = len(historical_data)
        frequency_stats = {}
        for num in range(1, 34):
            count = red_counter.get(num, 0)
            frequency_stats[num] = {
                'count': count,
                'frequency': round(count / total_draws * 100, 2) if total_draws > 0 else 0,
                'expected_frequency': round(100 / 33, 2)  # 理论频率
            }
        
        # 热号和冷号
        sorted_by_frequency = sorted(frequency_stats.items(), key=lambda x: x[1]['count'], reverse=True)
        hot_numbers = [num for num, stats in sorted_by_frequency[:10]]
        cold_numbers = [num for num, stats in sorted_by_frequency[-10:]]
        
        # 连号分析
        consecutive_stats = self.analyze_consecutive_numbers(historical_data)
        
        return {
            'frequency_stats': frequency_stats,
            'hot_numbers': hot_numbers,
            'cold_numbers': cold_numbers,
            'most_frequent': sorted_by_frequency[0][0] if sorted_by_frequency else None,
            'least_frequent': sorted_by_frequency[-1][0] if sorted_by_frequency else None,
            'consecutive_stats': consecutive_stats
        }
    
    def analyze_blue_balls(self, historical_data):
        """分析蓝球统计"""
        blue_counter = Counter()
        
        for record in historical_data:
            blue_counter[record['blue_ball']] += 1
        
        total_draws = len(historical_data)
        frequency_stats = {}
        for num in range(1, 17):
            count = blue_counter.get(num, 0)
            frequency_stats[num] = {
                'count': count,
                'frequency': round(count / total_draws * 100, 2) if total_draws > 0 else 0,
                'expected_frequency': round(100 / 16, 2)  # 理论频率
            }
        
        sorted_by_frequency = sorted(frequency_stats.items(), key=lambda x: x[1]['count'], reverse=True)
        
        return {
            'frequency_stats': frequency_stats,
            'most_frequent': sorted_by_frequency[0][0] if sorted_by_frequency else None,
            'least_frequent': sorted_by_frequency[-1][0] if sorted_by_frequency else None,
            'hot_numbers': [num for num, _ in sorted_by_frequency[:5]],
            'cold_numbers': [num for num, _ in sorted_by_frequency[-5:]]
        }
    
    def analyze_number_patterns(self, historical_data):
        """分析号码模式"""
        odd_even_stats = []
        big_small_stats = []
        sum_stats = []
        span_stats = []
        
        for record in historical_data:
            red_balls = record['red_balls']
            
            # 奇偶分析
            odd_count = sum(1 for num in red_balls if num % 2 == 1)
            odd_even_stats.append(odd_count)
            
            # 大小分析（1-16为小，17-33为大）
            big_count = sum(1 for num in red_balls if num > 16)
            big_small_stats.append(big_count)
            
            # 和值分析
            total_sum = sum(red_balls)
            sum_stats.append(total_sum)
            
            # 跨度分析
            span = max(red_balls) - min(red_balls)
            span_stats.append(span)
        
        return {
            'odd_even': {
                'average_odd_count': round(np.mean(odd_even_stats), 2),
                'odd_distribution': dict(Counter(odd_even_stats))
            },
            'big_small': {
                'average_big_count': round(np.mean(big_small_stats), 2),
                'big_distribution': dict(Counter(big_small_stats))
            },
            'sum_analysis': {
                'average_sum': round(np.mean(sum_stats), 2),
                'min_sum': min(sum_stats),
                'max_sum': max(sum_stats),
                'sum_range_distribution': self.get_sum_range_distribution(sum_stats)
            },
            'span_analysis': {
                'average_span': round(np.mean(span_stats), 2),
                'min_span': min(span_stats),
                'max_span': max(span_stats)
            }
        }
    
    def analyze_consecutive_numbers(self, historical_data):
        """分析连号情况"""
        consecutive_counts = []
        
        for record in historical_data:
            red_balls = sorted(record['red_balls'])
            consecutive_count = 0
            
            for i in range(len(red_balls) - 1):
                if red_balls[i + 1] - red_balls[i] == 1:
                    consecutive_count += 1
            
            consecutive_counts.append(consecutive_count)
        
        return {
            'average_consecutive': round(np.mean(consecutive_counts), 2),
            'consecutive_distribution': dict(Counter(consecutive_counts)),
            'max_consecutive': max(consecutive_counts),
            'periods_with_consecutive': sum(1 for count in consecutive_counts if count > 0)
        }
    
    def get_sum_range_distribution(self, sum_stats):
        """获取和值区间分布"""
        ranges = {
            '60-80': 0,
            '81-100': 0,
            '101-120': 0,
            '121-140': 0,
            '141-160': 0,
            '161-180': 0,
            '180+': 0
        }
        
        for s in sum_stats:
            if s <= 80:
                ranges['60-80'] += 1
            elif s <= 100:
                ranges['81-100'] += 1
            elif s <= 120:
                ranges['101-120'] += 1
            elif s <= 140:
                ranges['121-140'] += 1
            elif s <= 160:
                ranges['141-160'] += 1
            elif s <= 180:
                ranges['161-180'] += 1
            else:
                ranges['180+'] += 1
        
        return ranges
    
    def generate_ssq_charts(self, historical_data):
        """生成双色球图表数据"""
        charts = {}
        
        # 红球频率柱状图
        red_counter = Counter()
        for record in historical_data:
            for red in record['red_balls']:
                red_counter[red] += 1
        
        red_numbers = list(range(1, 34))
        red_frequencies = [red_counter.get(num, 0) for num in red_numbers]
        
        charts['red_frequency'] = {
            'type': 'bar',
            'data': {
                'x': red_numbers,
                'y': red_frequencies,
                'title': '红球出现频率统计'
            }
        }
        
        # 蓝球频率柱状图
        blue_counter = Counter()
        for record in historical_data:
            blue_counter[record['blue_ball']] += 1
        
        blue_numbers = list(range(1, 17))
        blue_frequencies = [blue_counter.get(num, 0) for num in blue_numbers]
        
        charts['blue_frequency'] = {
            'type': 'bar',
            'data': {
                'x': blue_numbers,
                'y': blue_frequencies,
                'title': '蓝球出现频率统计'
            }
        }
        
        # 和值趋势图
        periods = [record['period'] for record in reversed(historical_data[-50:])]
        sums = [sum(record['red_balls']) for record in reversed(historical_data[-50:])]
        
        charts['sum_trend'] = {
            'type': 'line',
            'data': {
                'x': periods,
                'y': sums,
                'title': '最近50期红球和值趋势'
            }
        }
        
        # 奇偶比例饼图
        odd_even_counts = [0] * 7  # 0-6个奇数
        for record in historical_data:
            odd_count = sum(1 for num in record['red_balls'] if num % 2 == 1)
            odd_even_counts[odd_count] += 1
        
        charts['odd_even_pie'] = {
            'type': 'pie',
            'data': {
                'labels': [f'{i}奇{6-i}偶' for i in range(7)],
                'values': odd_even_counts,
                'title': '奇偶比例分布'
            }
        }
        
        return charts
    
    def generate_dlt_statistics(self, historical_data):
        """生成大乐透统计数据"""
        stats = {
            'total_periods': len(historical_data),
            'date_range': {
                'start': historical_data[-1]['draw_date'] if historical_data else None,
                'end': historical_data[0]['draw_date'] if historical_data else None
            }
        }
        
        # 前区统计
        front_counter = Counter()
        for record in historical_data:
            for num in record['front_area']:
                front_counter[num] += 1
        
        total_draws = len(historical_data)
        front_frequency = {}
        for num in range(1, 36):
            count = front_counter.get(num, 0)
            front_frequency[num] = {
                'count': count,
                'frequency': round(count / total_draws * 100, 2) if total_draws > 0 else 0
            }
        
        # 后区统计
        back_counter = Counter()
        for record in historical_data:
            for num in record['back_area']:
                back_counter[num] += 1
        
        back_frequency = {}
        for num in range(1, 13):
            count = back_counter.get(num, 0)
            back_frequency[num] = {
                'count': count,
                'frequency': round(count / total_draws * 100, 2) if total_draws > 0 else 0
            }
        
        stats['front_area_stats'] = front_frequency
        stats['back_area_stats'] = back_frequency
        
        return stats
    
    def create_plotly_chart(self, chart_data):
        """创建Plotly图表"""
        chart_type = chart_data['type']
        data = chart_data['data']
        
        if chart_type == 'bar':
            fig = go.Figure(data=[
                go.Bar(x=data['x'], y=data['y'])
            ])
            fig.update_layout(title=data['title'])
        
        elif chart_type == 'line':
            fig = go.Figure(data=[
                go.Scatter(x=data['x'], y=data['y'], mode='lines+markers')
            ])
            fig.update_layout(title=data['title'])
        
        elif chart_type == 'pie':
            fig = go.Figure(data=[
                go.Pie(labels=data['labels'], values=data['values'])
            ])
            fig.update_layout(title=data['title'])
        
        else:
            return None
        
        return fig.to_json()
    
    def generate_trend_analysis(self, lottery_type='ssq', periods=100):
        """生成趋势分析"""
        historical_data = self.db_manager.get_recent_data(lottery_type, periods)
        
        if not historical_data:
            return {'error': '没有足够的历史数据'}
        
        # 计算移动平均
        if lottery_type == 'ssq':
            sums = [sum(record['red_balls']) for record in reversed(historical_data)]
            periods_list = [record['period'] for record in reversed(historical_data)]
            
            # 计算5期移动平均
            moving_avg = []
            for i in range(len(sums)):
                if i < 4:
                    moving_avg.append(sums[i])
                else:
                    avg = sum(sums[i-4:i+1]) / 5
                    moving_avg.append(round(avg, 2))
            
            return {
                'periods': periods_list,
                'actual_sums': sums,
                'moving_average': moving_avg,
                'trend_direction': 'up' if moving_avg[-1] > moving_avg[-10] else 'down'
            }
        
        return {'error': '暂不支持该彩票类型的趋势分析'}
    
    def export_statistics_report(self, lottery_type='ssq'):
        """导出统计报告"""
        stats = self.generate_statistics(lottery_type)
        
        report = {
            'generated_at': datetime.now().isoformat(),
            'lottery_type': lottery_type,
            'statistics': stats
        }
        
        # 保存到文件
        filename = f'lottery_report_{lottery_type}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.json'
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(report, f, ensure_ascii=False, indent=2)
        
        return filename